﻿using Bilibili.Common.Database;
using Bilibili.Common.Log;
using Bilibili.Model.Home;
using Bilibili.Model.Hot;
using Bilibili.Model.Parts;
using Bilibili.Model.Resource;
using Bilibili.WebClient.Common;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PCLUntils.Json;
using PCLUntils.Objects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Bilibili.WebClient.Api
{
    public sealed class VideoClient : ClientBase
    {
        public async Task<ReturnModel<TagsModel>> GetTags(int id)
        {
            try
            {
                var url = string.Format("http://api.bilibili.com/x/tag/hots?rid={0}&type=0&jsonp=json?rnd={1}", id, Current.Instance.Radom.Next(1, 9999));
                string result = await ApiClient.GetResults(url);
                var model = result.ParseObject<TagsModel>();
                return BuildSuccessResult(model);
            }
            catch (Exception ex)
            {
                return BuildExceptionResult<TagsModel>(ex);
            }
        }
        public async Task<ReturnModel<Hots>> GetHot(string pageIndex, string last_param)
        {
            try
            {
                ApiInfo apiInfo = new ApiInfo("https://app.bilibili.com/x/v2/show/popular/index", $"&fnval=16&fnver=0&force_host=0&fourk=1&idx={pageIndex}&last_param={last_param}&qn=32", false);
                var results = await ApiClient.GetResults(apiInfo);
                var model = results.ParseObject<Hots>();
                return BuildSuccessResult(model);
            }
            catch (Exception ex)
            {
                return BuildExceptionResult<Hots>(ex);
            }
        }
        public async Task<ReturnModel<HomeVideoModel>> GetRecommand(string currentPage)
        {
            try
            {
                var pull = (currentPage == "0").ToString().ToLower();
                ApiInfo apiInfo = new ApiInfo("https://app.bilibili.com/x/v2/feed/index", $"&flush=0&idx={currentPage}&login_event=2&network=wifi&open_event=&pull={pull}&qn=32&style=2", true);
                var result = await ApiClient.GetResultsUTF8Encode(apiInfo);
                var videoModels = result.ParseObject<HomeVideoModel>();
                return BuildSuccessResult(videoModels);
            }
            catch (Exception ex)
            {
                return BuildExceptionResult<HomeVideoModel>(ex);
            }
        }
        public async Task<ReturnModel<JObject>> GetParts(int currentPage, string tag, int id, string orderBy)
        {
            try
            {
                var conditions = $"&channel=bili&order={orderBy}&pn={currentPage}&ps=20&rid={id}";
                if (tag.Length != 0 && tag != "全部")
                    conditions += $"&tag_name={Uri.EscapeDataString(tag)}";
                ApiInfo apiInfo = new ApiInfo("https://app.bilibili.com/x/v2/region/show/child/list", conditions, false);
                string results = await ApiClient.GetResults(apiInfo);
                var obj = results.ToJObject();
                return BuildSuccessResult(obj);
            }
            catch (Exception ex)
            {
                return BuildExceptionResult<JObject>(ex);
            }
        }
        public async Task<ReturnModel<DHModel>> GetPartRecommand(int id)
        {
            try
            {
                string url = string.Format("http://www.bilibili.com/index/ding/{0}.json?rnd={1}", id, Current.Instance.Radom.Next(1, 9999));
                string results = await ApiClient.GetResultsGZip(url);
                DHModel model = results.ParseObject<DHModel>();
                return BuildSuccessResult(model);
            }
            catch (Exception ex)
            {
                return BuildExceptionResult<DHModel>(ex);
            }
        }
        public async Task<ReturnModel<List<QualityInfo>>> GetAnimeQualities(long mid, int seasonType)
        {
            var qualities = new List<QualityInfo>();
            try
            {
                ApiInfo apiInfo = new ApiInfo($"https://api.bilibili.com/pgc/player/web/playurl?cid={mid}&otype=json&type=&quality=64&module=bangumi&season_type={seasonType}",
                  SettingHelper.UseDASH ? "&fourk=1&fnver=0&fnval=16" : string.Empty, true, ApiProvider.Instance.WebVideoKey, true);
                var results = await ApiClient.GetResultsUTF8Encode(apiInfo);
                var jobj = results.ToJObject();
                if (jobj["code"].ToInt32() == 0 && !results.Contains("8986943"))
                {
                    var dashModel = JsonConvert.DeserializeObject<DashModel>(jobj["result"].ToString());
                    foreach (var item in dashModel.accept_description)
                    {
                        var qn = dashModel.accept_quality[dashModel.accept_description.IndexOf(item)];
                        qualities.Add(new QualityInfo(qn, item));
                    }
                    if (!ApiProvider.Instance.IsLogin)
                    {
                        qualities = qualities.Where(x => x.Qn <= 32).ToList();
                        foreach (var item in qualities)
                            item.Description += "(登录享受更多清晰度)";
                    }
                    else
                    {
                        var vipInfo = SettingHelper.UserInfo.Data.Card.Vip;
                        if (vipInfo.IsNotEmpty() && vipInfo.VipType != 0)
                            qualities = qualities.Where(x => x.Qn != 74 && x.Qn <= 80).ToList();
                    }
                    qualities = qualities.OrderBy(x => x.Qn).ToList();
                }
                else
                    qualities = GetDefaultQualities();
            }
            catch (Exception ex)
            {
                LogManager.Instance.LogError("GetAnimeQualities", ex);
                qualities = GetDefaultQualities();
            }
            return BuildSuccessResult(qualities);
        }
        public async Task<ReturnModel<List<QualityInfo>>> GetVideoQualitys(string aid, long cid)
        {
            try
            {
                ApiInfo apiInfo = new ApiInfo($"https://api.bilibili.com/x/player/playurl?avid={aid}&cid={cid}&qn=64&type=&otype=json",
                    SettingHelper.UseDASH ? "&fourk=1&fnver=0&fnval=16" : string.Empty, true, ApiProvider.Instance.AndroidVideoKey, true);
                var results = await ApiClient.GetResults(apiInfo);
                var model = results.ParseObject<VideoUrlInfo>();
                if (model.code == 0)
                {
                    if (ApiProvider.Instance.AccessKey.IsEmpty())
                    {
                        var list = GetDefaultQualities();
                        return BuildSuccessResult(list);
                    }
                    else
                    {
                        List<QualityInfo> list = new List<QualityInfo>();
                        for (int i = 0; i < model.data.accept_quality.Count; i++)
                            list.Add(new QualityInfo(model.data.accept_quality[i], model.data.accept_description[i], model.data.dash));
                        return BuildSuccessResult(list);
                    }
                }
                else
                    return BuildSuccessResult<List<QualityInfo>>(default);
            }
            catch (Exception ex)
            {
                LogManager.Instance.LogError("GetVideoQualitys", ex);
                return BuildExceptionResult<List<QualityInfo>>(ex);
            }
        }
        private List<QualityInfo> GetDefaultQualities()
        {
            if (ApiProvider.Instance.IsLogin)
            {
                return new List<QualityInfo> {
                new QualityInfo(16,"流畅"),
                new QualityInfo(32,"清晰"),
                new QualityInfo(64,"高清"),
                new QualityInfo(80,"超清")
            };
            }
            else
            {
                return new List<QualityInfo> {
                new QualityInfo(16,"流畅(登录享受更多清晰度)"),
                new QualityInfo(32,"清晰(登录享受更多清晰度)")
            };
            }
        }
    }
}